package math;

import java.util.StringTokenizer;

public class Vector3f{
	public static final Vector3f ZERO = new Vector3f();
	public static final Vector3f ONE = new Vector3f(1,1,1);
	public static final Vector3f NORMAL_X = new Vector3f(1,0,0);
	public static final Vector3f NORMAL_Y = new Vector3f(0,1,0);
	public static final Vector3f NORMAL_Z = new Vector3f(0,0,1);
	
	public float x, y, z;

	public Vector3f() {
		set(0, 0, 0);
	}
	
	public Vector3f(Vector3f vec) {
		set(vec);
	}
	
	public Vector3f(Vector3i vec) {
		set(vec.x, vec.y, vec.z);
	}	

	public Vector3f(float v) {
		this(v, v, v);
	}

	public Vector3f(float x, float y, float z) {
		set(x, y, z);
	}
	
	
	public Vector3f add(float x, float y, float z) {
		this.x += x;
		this.y += y;
		this.z += z;
		return this;
	}
	
	public Vector3f add(Vector3f vec) {
		return add(vec.x, vec.y, vec.z);
	}
	
	public static Vector3f add(Vector3f a, Vector3f b) {
		return new Vector3f(a.x + b.x, a.y + b.y, a.z + b.z);
	}
	
	public Vector3f sub(float x, float y, float z) {
		this.x -= x;
		this.y -= y;
		this.z -= z;
		return this;
	}
	
	public Vector3f sub(Vector3f vec) {
		return sub(vec.x, vec.y, vec.z);
	}
	
	public Vector3f mult(float f) {
		return mult(f, f, f);
	}
	
	public Vector3f mult(float x, float y, float z) {
		this.x *= x;
		this.y *= y;
		this.z *= z;
		return this;
	}
	
	public Vector3f mult(Vector3f vec) {
		return mult(vec.x, vec.y, vec.z);
	}
	
    public static Vector3f mult(Vector3f a, Vector3f b) {
        return new Vector3f(a.x * b.x, a.y * b.y, a.z * b.z);
    }

	public Vector3f divide(float f) {
		return divide(f, f, f);
	}
	
	public Vector3f divide(float x, float y, float z) {
		this.x /= x;
		this.y /= y;
		this.z /= z;
		return this;
	}
	
	public Vector3f divide(Vector3f vec) {
		return divide(vec.x, vec.y, vec.z);
	}
	
	public float length() {
		return (float)Math.sqrt(x * x + y * y + z * z);
	}

	public static float distance(Vector3f vec1, Vector3f vec2) {
		Vector3f vec = vec1.sub(vec2);
		return vec.length();
	}

	public Vector3f copy() {
		return new Vector3f(this);
	}
	
	public float[] toArray() {
		return new float[]{x,y,z};
	}	
	
	public Vector3f reset() {
		x = y = z = 0;
		return this;
	}

	public Vector3f normalize() {
		float length = length();
		if (length > 0) {
			x /= length;
			y /= length;
			z /= length;
		}
		return this;
	}
	
	public float dot(Vector3f vec) {
		return x * vec.x + y * vec.y + z * vec.z;
	}
	
	public float x() {
		return x;
	}
	
	public Vector3f x(float x) {
		this.x = x;
		return this;
	}
	
	public float y() {
		return y;
	}
	
	public Vector3f y(float y) {
		this.y = y;
		return this;
	}
	
	public float z() {
		return z;
	}
	
	public Vector3f z(float z) {
		this.z = z;
		return this;
	}

	public boolean equals(Object o) {
		if(o instanceof Vector3f) {
			Vector3f v = (Vector3f)o;
			return x == v.x && y == v.y && z == v.z;
		}
		
		return false;
	}

	public Vector3f set(float x, float y, float z) {
		this.x = x;
		this.y = y;
		this.z = z;
		return this;
	}
	
	public Vector3f set(Vector2f vec) {
		return set(vec.x, vec.y, 0);
	}
	
	public Vector3f set(Vector2f vec, float z) {
		return set(vec.x, vec.y, z);
	}
	
	public Vector3f set(Vector3f vec) {
		return set(vec.x, vec.y, vec.z);
	}

	public Vector3f set(Vector4f vec) {
		return set(vec.x, vec.y, vec.z);
	}

	public String println() {
		return "" + x + " " + y + " " + z;
	}
	
    public double getRadiansX(){
   	 return Math.toRadians(x);
   }
   
   public double getRadiansY(){
  	 return Math.toRadians(y);
  }
	
	public static Vector3f parse(StringTokenizer tokenizer) {
		float x = Float.valueOf(tokenizer.nextToken());
		float y = Float.valueOf(tokenizer.nextToken());
		float z = Float.valueOf(tokenizer.nextToken());
		return new Vector3f(x, y, z);
	}
    
	//--------------------------------------------------------------only for vector 3f
	public Vector3f cross(Vector3f vec) {
		return new Vector3f(y * vec.z - vec.y * z, z * vec.x - vec.z * x, x * vec.y - vec.x * y);
	}
	
	public Vector3f cross(Vector3f vec1,Vector3f vec2) {
		return new Vector3f(vec1.y * vec2.z - vec2.y * vec1.z, vec1.z * vec2.x - vec2.z * vec1.x, vec1.x * vec2.y - vec2.x * vec1.y);
	}
}
